import {fabric} from 'fabric';
import gsApi from '@/api/gsApi';

export default class CanvasManager{
  canvasId = ''
  // 当前地图
  mapName=''
  // 当前的canvas
  canvas=''
  // 当前地图图片
  img=''
  // 拖动地图状态
  moveStatus=false;
  // 编辑地图状态
  editStatus=true;
  // 打点状态
  clickStatus=true;
  //显示实时位置的三角形对象
  locatTri;
  //手动打点的圆形对象
  positionCircle='';

  mouseUp=false;

  mouseDown=false;

// 点计画布交互产生的暂存数据
  tempPosition;

  constructor({canvasId,mapName},opt){
    let defaultOpt={
      width: window.innerWidth,
      height: window.innerHeight-100,
      isDrawingMode: false,
      selection: false, // 是否启用组选择
      devicePixelRatio: true, // Retina 高清屏 屏幕支持
      allowTouchScrolling:false
    }
    Object.assign(defaultOpt, opt);
    this.canvasId=canvasId;
    this.mapName=mapName;

    // 这一步必须要在存在DOM 时候执行，所以一般放在 VUE 的 mounted 事件里
    this.canvas = new fabric.Canvas(canvasId,defaultOpt);
    //用于实现右键功能
    // $(".upper-canvas").contextmenu(onContextmenu);
    this.__init();
  }

  __init(){
    // 加载图片
    this.__loadImg(this.mapName);

    // 启动canvas 的鼠标事件
    this.enableMouseFun();
  }

  reloadImg(mapName){
    // 清除画布所有的内容
    this.canvas.remove(...this.canvas.getObjects());
    this.__loadImg(mapName);
  }

  moveImg(){
    this.canvas.remove(...this.canvas.getObjects());
  }

  /**
   * 清除画布除了地图的元素
   */
  clearObject(){
    this.canvas.remove(...this.canvas.getObjects());
    this.canvas.add(this.img);
  }
  /**
   * 清楚画布的地图
   */
  clearMap(){
    this.canvas.remove(...this.canvas.getObjects());
  }

  /**
   * 清除画布上所有的圆 
   */
  clearObjectCircle(){
    this.canvas.remove(...this.canvas.getObjects('circle'));
  }

  /** 
   * 清除画布上所有的文字
   */
  clearObjectText(){
    this.canvas.remove(...this.canvas.getObjects('text'));
  }
    /**
   * 绘制定点
   * @param point 点完整数据
   * @param imgHeight 地图高度，转换需要
   */
  drawPosition({positionName,dataManager}){
      const position = dataManager.positionMap.get(positionName)
      const imgHeight=this.img.height
      const circle=new fabric.Circle({
        radius: 5,
        fill: '#228B22',
        stroke: '#333333',
        strokeWidth: 0.5,
        left: position.gridX,
        //  记得需要转换坐标系的，canvas 上显示坐标系 和 机器人导航的坐标系
        top: imgHeight-position.gridY,
        selectable: false,
        hasBorders: false,
        hasControls: false,
        originX: 'center',
        originY: 'center',
        hoverCursor: 'default',     //这个hoverCursor里可填的值和css里的鼠标指针样式的一样，默认是十字指针
      })
      var text = new fabric.Text(positionName, { 
        fontSize:5,
        left: position.gridX-6, 
        top: imgHeight-position.gridY-11,
        textAlign: 'center',
        selectable: false,
        hoverCursor: 'default'
      });
      this.canvas.add(text);
      if(positionName=='Origin'){
        circle.set('fill','#FF8C00');
      }
      this.canvas.add(circle);
}
// 绘制当前位置点
drawCurrentPosition(point){
    let imgHeight = this.img.height;
    this.circle=new fabric.Circle({
      radius: 5,
      fill: 'red',
      stroke: '#333333',
      strokeWidth: 0.5,
      angle:point.angle,
      left: point.gridPosition.x,
      //  记得需要转换坐标系的，canvas 上显示坐标系 和 机器人导航的坐标系
      top: imgHeight-point.gridPosition.y,
      selectable: false,
      hasBorders: false,
      hasControls: false,
      originX: 'center',
      originY: 'center',
      hoverCursor: 'default'
    })
    // console.log(circle);
    this.canvas.add(this.circle);
}
//先用下面的show显示位置，再用这个函数更新位置
moveCurrentPosition(point){
  let imgHeight = this.img.height;
  let left = point.gridPosition.x;
  let top = imgHeight-point.gridPosition.y;
  let angle = -point.angle+90;
  // console.log(left + ' ' + top + ' ' + angle)
  //1.用重新打点的方式显示实时位置
  // this.locatTri.set("left",left);
  // this.locatTri.set("top",top)
  // this.locatTri.set("angle",angle)
  // this.canvas.renderAll()
  //2.用动画的效果处理
  this.locatTri.animate('left',left,{
    onChange: this.canvas.renderAll.bind(this.canvas)
  })
  this.locatTri.animate('top',top,{
    onChange: this.canvas.renderAll.bind(this.canvas)
  })
  this.locatTri.animate('angle',angle,{
    onChange: this.canvas.renderAll.bind(this.canvas)
  })

}

//小车移动时实时显示当前位置点
showCurrentPosition(point){
  this.canvas.remove(this.locatTri)
  let imgHeight = this.img.height;
  this.locatTri=new fabric.Triangle({
    height:10,
    width:6,
    // radius: 4,
    fill: '#FFD700',
    stroke: 'red',
    strokeWidth: 0.5,
    angle:-point.angle+90,    //角度要注意转换！
    left: point.gridPosition.x,
    //  记得需要转换坐标系的，canvas 上显示坐标系 和 机器人导航的坐标系
    top: imgHeight-point.gridPosition.y,
    selectable: false,
    hasBorders: false,
    hasControls: false,
    originX: 'center',
    originY: 'center',
    hoverCursor: 'default'
  })
  // console.log(this.canvas.getObjects())
  this.canvas.add(this.locatTri);
}

  // 这里是异步加载的要注意处理时许的问题
  __loadImg(mapName){
    // 加载某张地图，就设为当前地图
    this.mapName = mapName;
    const imgUrl=gsApi.getMapPngUrl(mapName);
    new fabric.Image.fromURL(imgUrl,oImg=>{
      oImg.id = mapName
      oImg.evented = false
      this.img=oImg
      this.canvas.add(this.img);
      this.zoomTofit()
    })
  }

  loadScanningImg(){
    console.log("获取扫描地图执行一次")
    const imgUrl=gsApi.getScanningPngUrl();
    new fabric.Image.fromURL(imgUrl,oImg=>{
      // this.img=oImg
      oImg.id = (new Date()).getTime();
      oImg.evented = false
      this.canvas.add(oImg);
      this.zoomTofit();
    })
    // console.log(scanningImg)
    // this.canvas.add(scanningImg);
    // this.zoomTofit();
  }

  loadScanMap()
  {
    this.canvas.add(this.img);
  }

  /*
  * 加载实时扫描地图
  */
  loadScanningMap(){
    let imageUrl = gsApi.getMapPngUrl();
    console.log(imageUrl);
  }

  /**
   * 调整画布缩放平移
   */
  zoomTofit(){
    // 先还原缩放比例与位置
    this.canvas.setZoom(1)
    this.canvas.absolutePan({ x: 0, y: 0 })
    // 遍历所有对对象，获取最小坐标，最大坐标,即四个角的坐标
    const objects = this.canvas.getObjects()
    let rect, minX, minY, maxX, maxY
    if (objects.length > 0) {
      rect = objects[0].getBoundingRect()
      minX = rect.left
      minY = rect.top
      maxX = rect.left + rect.width
      maxY = rect.top + rect.height
    } else {
      return
    }
    // 计算平移坐标,居中
    const panX = (maxX - minX - this.canvas.width) / 2 + minX
    const panY = (maxY - minY - this.canvas.height) / 2 + minY
    // 开始平移
    this.canvas.absolutePan({ x: panX, y: panY })
    // 计算缩放比例
    const zoom = Math.min(this.canvas.width / (maxX - minX), this.canvas.height / (maxY - minY))
    // 计算缩放中心
    const zoomPoint = new fabric.Point(this.canvas.width / 2, this.canvas.height / 2)
    // 开始缩放
    this.canvas.zoomToPoint(zoomPoint, zoom)
  }

  /**
   * 激活鼠标功能
   */
  enableMouseFun(){
    this.onMouseDown(this.doMouseDown);
    this.onMouseUp();
    this.onMouseMove();
    this.onMouseWheel();
  }


  onMouseDown(doMouseDown=()=>{}){
    //当鼠标按下事件发生时，会从这里开始触发函数
    this.canvas.on('mouse:down', (options) => {
      // 非打点状态
      if(!this.clickStatus){
        this.moveStatus=true;
      }
      // 编辑状态 同时是 打点状态时候
      if(this.editStatus&& this.clickStatus){
        // 这里设置成回调函数，方便自由定义
        doMouseDown(options,this)
      }
    })
  }

  /**
   * 打点状态时候要做的操作
   * 做两件事，第一向tempPosition中存入点击的点位置信息，第二是画一个圆点
   * @param options
   * @param canvasManager
   */
  doMouseDown(options,canvasManager){
    //每次点击清除上次画的点
    // canvasManager.clearObject();
    canvasManager.canvas.remove(canvasManager.positionCircle)
    // 1.获取转换过的坐标
    const positionX = Math.round(canvasManager.canvas.getPointer(options.e).x)
    const positionY = Math.round(canvasManager.canvas.getPointer(options.e).y)

    // 2.记录数据
    const pointName = positionX.toString();
    //0初始点，1充电点，2导航点，3RFID点，4注水点，5排水点
    const currentPosition= {
      angle:0,
      x: positionX,
      y: positionY,
      mapName:canvasManager.mapName,
      name: pointName,
      type:2
    }

    canvasManager.tempPosition = currentPosition;
    console.log(canvasManager.tempPosition);
    // 3.视图渲染

    // 3.2 绘制点
    canvasManager.positionCircle=canvasManager.getCircleElement({
      x:positionX,
      y:positionY,
      radius:5,
      color:'red',
    })
    canvasManager.canvas.add(canvasManager.positionCircle);
    canvasManager.startPosition();
  }

  async startPosition(){
    const positionBean = this.generateDestination();
    if(positionBean == null){
      // this.$message.info('请选择点')
      return
    }
    try {
      console.log(positionBean)
      const res = await gsApi.navigate(positionBean);
      if(res.data.msg==='successed'){
        // this.$message.success(`执行导航`)
      }else{
        // this.$message.error(res.data.msg);
      }
    }catch (err) {
      console.log(err);
      // this.$message.error('网络异常')
    }
  }

  onMouseMove(doMouseMove=()=>{}){
    this.canvas.on('mouse:move', (options) => {
      // if(!this.clickStatus && this.moveStatus){
      //   const delta = new fabric.Point(options.e.movementX, options.e.movementY);
      //   this.canvas.relativePan(delta)
      // }
      if(this.moveStatus){
        console.log('执行移动')
        const delta = new fabric.Point(options.e.movementX, options.e.movementY);
        this.canvas.relativePan(delta)
      }
      else if(this.editStatus && this.clickStatus){
        // 这里设置成回调函数，方便自定义扩展
        doMouseMove(options,this)
      }
    })
  }

  onMouseUp(doMouseUp=()=>{}){
    this.canvas.on('mouse:up',options=>{
      if(!this.clickStatus){
        this.moveStatus=false;
      }
      else{
        // 这里设置成回调函数，方便自定义扩展
        doMouseUp(options,this)
      }
    })
  }

  onMouseWheel(){
    // 滚动缩放画布大小
    this.canvas.on('mouse:wheel', (options) => {
      let zoom = (options.e.deltaY > 0 ? -0.1 : 0.1) + this.canvas.getZoom()
      // 最小为原来的1/10
      zoom = Math.max(0.1, zoom)
      // 最大是原来的3倍
      zoom = Math.min(5, zoom)
      // 在中心缩放
      const zoomPoint = new fabric.Point(this.canvas.width / 2, this.canvas.height / 2)
      this.canvas.zoomToPoint(zoomPoint, zoom)
    })
  }

  /**
   * 返回一个fabric.Circle
   * 每次点击画一个点
   * @param x
   * @param y
   * @param radius
   * @param color
   */
  getCircleElement({x,y,radius,color}) {
    return new fabric.Circle({
      radius: radius,
      fill: color,
      stroke: '#333333',
      strokeWidth: 0.5,
      left: x,
      top: y,
      selectable: false,
      hasBorders: false,
      hasControls: false,
      originX: 'center',
      originY: 'center',
      hoverCursor: 'default'
    })
  }
  //生成正确格式的request提交给gsApi里的insertPosition用
  generatePosition(){
    const imgHeight=this.img.height;
    // 坐标系之间需要做转换.主要是y轴
    // const positionBean = gsApi.createPositionBean({
    //   angle:this.tempPosition.angle,
    //   x:this.tempPosition.x,
    //   y:imgHeight-this.tempPosition.y,
    //   mapName:this.tempPosition.mapName,
    //   name:this.tempPosition.name,
    //   type:this.tempPosition.type
    // })
    // return positionBean;
    return {
      "angle":this.tempPosition.angle,
      "gridX":this.tempPosition.x,
      "gridY":imgHeight-this.tempPosition.y,
      "mapName":this.tempPosition.mapName,
      "name":this.tempPosition.name,
      "type":this.tempPosition.type
    }
  }

  generateDestination(){
    const imgHeight=this.img.height;
    // 坐标系之间需要做转换.主要是y轴
    // const positionBean = gsApi.createPositionBean({
    //   angle:this.tempPosition.angle,
    //   x:this.tempPosition.x,
    //   y:imgHeight-this.tempPosition.y,
    //   mapName:this.tempPosition.mapName,
    //   name:this.tempPosition.name,
    //   type:this.tempPosition.type
    // })
    // return positionBean;
    return {
      "destination":{
      "angle":null,
      "gridPosition":{  // 栅格化坐标
        "x":this.tempPosition.x,
        "y":imgHeight-this.tempPosition.y,
        }
      }
    }
  }

}
